/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ejb.negocio;

import ejb.dao.ClienteDAOLocal;
import ejb.dao.PedidoDAOLocal;
import ejb.dao.ProductoDAOLocal;

import ejb.excepciones.ExcepcionExistencias;

import entidades.Cliente;
import entidades.EstadoPedido;
import entidades.LineaPedido;
import entidades.Pedido;
import entidades.Producto;
import entidades.TipoUsuario;
import entidades.Usuario;
import java.util.Calendar;
import java.util.List;
import java.util.Vector;
import javax.ejb.EJB;
import javax.ejb.Stateful;

/**
 *
 * @author ribadas
 */
@Stateful
public class CompraService implements CompraServiceRemote, CompraServiceLocal {

    @EJB
    ProductoDAOLocal productoFacade;
    @EJB
    ClienteDAOLocal clienteFacade;
    @EJB
    PedidoDAOLocal pedidoFacade;
    private List<ProductoCompra> carroCompra = null;
    private Cliente cliente = null;
    private boolean confirmado = false;

    public void inicializarCarroCompra() {
        this.carroCompra = new Vector<ProductoCompra>();
        this.cliente = null;
        this.confirmado = false;
    }

    public void anadirProducto(long idProducto, long cantidad) {
        if (carroCompra == null) {
            inicializarCarroCompra();
        }

        if (!confirmado) {
            Producto p = productoFacade.buscarPorId(idProducto);
            if (p != null) {  // Existe el producto
                ProductoCompra itemEncontrado = buscarItem(p);

                if (itemEncontrado != null) {
                    itemEncontrado.incrementarCantidad(cantidad);
                } else {
                    carroCompra.add(new ProductoCompra(p, cantidad));
                }
            }
        }
    }

    public void incrementarCantidad(long idProducto, long incremento) {
        if (!confirmado) {
            ProductoCompra itemEncontrado = buscarItem(idProducto);
            if (itemEncontrado != null) {
                itemEncontrado.incrementarCantidad(incremento);
            }
        }
    }

    public void decrementarCantidad(long idProducto, long reduccion) {
        if (!confirmado) {
            ProductoCompra itemEncontrado = buscarItem(idProducto);
            if (itemEncontrado != null) {
                itemEncontrado.decrementarCantidad(reduccion);
            }
        }
    }

    public void vaciarCarro() {
        if (carroCompra == null) {
            inicializarCarroCompra();
        } else {
            carroCompra.clear();
            confirmado = false;
        }
    }

    public void confirmarCarro() throws ExcepcionExistencias {
        if (confirmarExistenciasCarro()) {
            this.confirmado = true;
        }
    }

    public void eliminarProducto(long idProducto) {
        if (!confirmado) {
            if (carroCompra != null) {
                int idx = 0;
                for (ProductoCompra item : carroCompra) {
                    if (item.getProducto().getId() == idProducto) {
                        carroCompra.remove(idx);
                        break; // salir del bucle
                    }
                    idx++;
                }
            }
        }
    }

    public void actualizarCantidad(long idProducto, long nuevaCantidad) {
        if (!confirmado) {
            ProductoCompra itemEncontrado = buscarItem(idProducto);

            if (itemEncontrado != null) {
                itemEncontrado.setCantidad(nuevaCantidad);
            }
        }
    }

    private boolean confirmarExistenciasCarro() throws ExcepcionExistencias {
        boolean existenciasConfirmadas = true;
        Producto p;
        if (carroCompra != null) {
            for (ProductoCompra item : carroCompra) {
                if (!productoDisponible(item.getProducto().getId(), item.getCantidad())) {
                    existenciasConfirmadas = false;
                    throw new ExcepcionExistencias(item.getProducto().getId(),
                            item.getCantidad(),
                            item.getProducto().getDescripcion());
                }
            }
        } else {
            existenciasConfirmadas = false;
        }

        return existenciasConfirmadas;
    }

    public boolean productoDisponible(long idProducto, long cantidad) {
        Producto p;
        p = productoFacade.buscarPorId(idProducto);

        return (p.getExistencias() >= cantidad);
    }

    public void establecerCliente(long idCliente) {
        Cliente c = clienteFacade.buscarPorId(idCliente);
        if (c != null) {
            this.cliente = c;
        }
    }

    public Pedido generarPedido() {
        Pedido pedidoGenerado = null;
        List<LineaPedido> lineasPedidoGenerado = new Vector<LineaPedido>();

        if (confirmado && cliente != null) {
            pedidoGenerado = new Pedido(cliente, Calendar.getInstance().getTime(), EstadoPedido.PENDIENTE);

            for (ProductoCompra item : carroCompra) {
                Producto producto = productoFacade.buscarPorId(item.getProducto().getId());
                System.err.println(">>Pedido:" + pedidoGenerado.toString());
                long cantidadCompra = Math.min(item.getCantidad(), producto.getExistencias());
                LineaPedido linea = new LineaPedido(pedidoGenerado, producto,
                        cantidadCompra, producto.getPrecio(),
                        calcularDescuento(cliente, producto, cantidadCompra));
                System.err.println(">>  linea:" + linea.toString());
                lineasPedidoGenerado.add(linea);
            }

            pedidoGenerado.setLineasPedido(lineasPedidoGenerado);
            pedidoGenerado = pedidoFacade.crear(pedidoGenerado);  // Crea el pedido e inserta las lineas

            // Inicializar el carro de la compra para crear otro pedido
            vaciarCarro();
        }

        // Devolver null o el pedido generado
        return pedidoGenerado;
    }

    public List<ProductoCompra> obtenerCarroCompra() {
        return carroCompra;
    }

    public double calcularImporteTotal() {
        double total = 0.0;

        if (carroCompra != null) {
            for (ProductoCompra p : carroCompra) {
                double parcial = (p.getCantidad() * p.getProducto().getPrecio());
                if (cliente != null) {
                    parcial = parcial * (1 - calcularDescuento(cliente, p.getProducto(), p.getCantidad()) / 100);
                }
                total = total + parcial;
            }
        }

        return total;
    }

    // Metodos privados
    private ProductoCompra buscarItem(long idProducto) {
        ProductoCompra itemEncontrado = null;
        if (carroCompra != null) {
            for (ProductoCompra item : carroCompra) {
                if (item.getProducto().getId() == idProducto) {
                    itemEncontrado = item;
                    break;  // Salir del bucle
                }
            }
        }
        return itemEncontrado;
    }

    private ProductoCompra buscarItem(Producto p) {
        return buscarItem(p.getId());
    }

    private double calcularDescuento(Cliente cliente, Producto producto, long cantidadCompra) {
        // No se hacen descuentos (... por ahora)
        return 0.0;
    }
// Add business logic below. (Right-click in editor and choose
// "Insert Code > Add Business Method")
}
